﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Teigha.DatabaseServices;

namespace Com.OpenCode.DwgConvert.Model
{
    /// <summary>
    /// 默认的转换对象
    /// 里面只提供dwg文件的打开和关闭操作
    /// 不对数据进行任何处理
    /// </summary>
    public abstract class AbstractDwgConvert : AbstractDataConvert
    {
        /// <summary>
        /// 重写任务类型
        /// </summary>
        public override TaskType TaskType
        {
            get
            {
                return TaskType.CadToShapeFile;
            }
        }

        /// <summary>
        /// 输入的数据源
        /// </summary>
        public Database DwgDatabase { get; set; }

        /// <summary>
        /// 重写实现dwg数据检查
        /// </summary>
        protected override void OnCheck()
        {
            base.OnCheck();
            AddInfoLogItem("正在检查Dwg数据源");
            InputDatasource.Count = 0;
            DwgDatabase = new Database(false, false);
            DwgDatabase.ReadDwgFile(InputDatasource.Source, FileOpenMode.OpenForReadAndReadShare, false, "");
            BlockTableRecord blockTableRecord = (BlockTableRecord)DwgDatabase.CurrentSpaceId.GetObject(OpenMode.ForRead);
            foreach (ObjectId item in blockTableRecord)
            {
                InputDatasource.Count++;
            }
            OnCheckingEvent(new DataConvertProcessEventArgs(this, InputDatasource.Count, 0));
            AddInfoLogItem(string.Format("Dwg数据源位置:{0}", InputDatasource.Source));
            AddInfoLogItem(string.Format("Dwg数据总数:{0}", InputDatasource.Count));
            string outPut;
            if (OutputDatasource == null)
            {
                AddWraingLogItem("没有指定成果保存位置,结果会保存在dwg文件所在位置");
                FileInfo fileInfo = new FileInfo(InputDatasource.Source);
                outPut = Path.Combine(fileInfo.DirectoryName, InputDatasource.Name);
            }
            else
            {
                outPut = OutputDatasource.Source;
            }
            outPut = CreateOutputDatasource(outPut);
            OutputDatasource = new TaskDatasource(outPut);
            AddInfoLogItem(string.Format("转换结果保存位置:{0}", OutputDatasource.Source));
            Description = "";
            Description += $"Dwg转Shp任务\r\n";
            Description += $"Dwg数据源位置:{InputDatasource.Source}\r\n";
            Description += $"Dwg数据总数:{InputDatasource.Count}\r\n";
            Description += $"转换结果保存位置:{OutputDatasource.Source}";
        }

        /// <summary>
        /// 检查后关闭数据
        /// </summary>
        protected override void OnAfterCheck()
        {
            base.OnAfterCheck();
            if (DwgDatabase != null)
            {
                DwgDatabase.CloseInput(true);
                DwgDatabase.Dispose();
                DwgDatabase = null;
            }
        }

        /// <summary>
        /// 检查输出的shp文件路径
        /// 递归检查，一直到文件不存在
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        protected virtual string CreateOutputDatasource(string path)
        {
            DirectoryInfo outputFileInfo = new DirectoryInfo(path);
            if (!outputFileInfo.Exists)
            {
                outputFileInfo.Create();
                return path;
            }
            else
            {
                string nextFile = Path.Combine(outputFileInfo.FullName + "_1");
                return CreateOutputDatasource(nextFile);
            }
        }

        /// <summary>
        /// 数据转换具体逻辑
        /// </summary>
        protected override void OnConvert()
        {
            base.OnConvert();
            int index = 0;
            double oldPercent = 0.0;
            DataConvertProcessEventArgs dataConvertProcessArgs = new DataConvertProcessEventArgs(this, index, 0);
            AddInfoLogItem($"打开dwg数据源({InputDatasource.Source})");
            DwgDatabase = new Database(false, false);
            DwgDatabase.ReadDwgFile(InputDatasource.Source, FileOpenMode.OpenForReadAndReadShare, false, "");
            BlockTableRecord blockTableRecord = (BlockTableRecord)DwgDatabase.CurrentSpaceId.GetObject(OpenMode.ForRead);
            AddInfoLogItem($"开始转换dwg数据({InputDatasource.Source})");
            foreach (ObjectId item in blockTableRecord)
            {
                ConvertDwgObject(item.GetObject(OpenMode.ForRead) as Entity);
                index++;
                double percent = (index * 100.0) / (InputDatasource.Count * 1.0);
                if (percent - oldPercent > 1)
                {
                    AddInfoLogItem($"转换进度({(int)percent}%),当前第({index})条/共({InputDatasource.Count})条");
                    dataConvertProcessArgs.Percent = percent;
                    dataConvertProcessArgs.Current = index;
                    OnConvertingEvent(dataConvertProcessArgs);
                    oldPercent = percent;
                }
            }
            AddInfoLogItem($"保存dwg元数据信息");
            dataConvertProcessArgs.Percent = 100;
            dataConvertProcessArgs.Current = InputDatasource.Count;
            OnConvertingEvent(dataConvertProcessArgs);
            AddInfoLogItem($"转换进度(100%),当前第({index})条/共({InputDatasource.Count})条");
            AddInfoLogItem($"数据转换已经完成({InputDatasource.Source})");
        }

        /// <summary>
        /// 转换之前检查输出结果
        /// </summary>
        protected override void OnBeforeConvert()
        {
            base.OnBeforeConvert();
            AddInfoLogItem($"创建输出结果Shp文件");
            if (Directory.Exists(OutputDatasource.Source))
            {
                AddInfoLogItem($"存在同名的输出结果({OutputDatasource.Source}),正在删除目录");
                Directory.Delete(OutputDatasource.Source, true);
            }
            AddInfoLogItem($"创建结果保存目录({OutputDatasource.Source})");
            Directory.CreateDirectory(OutputDatasource.Source);
        }

        /// <summary>
        /// 转换后
        /// </summary>
        protected override void OnAfterConvert()
        {
            base.OnAfterConvert();
            if (DwgDatabase != null)
            {
                DwgDatabase.CloseInput(true);
                DwgDatabase.Dispose();
                DwgDatabase = null;
            }
        }

        /// <summary>
        /// 转换每一个数据
        /// </summary>
        /// <param name="entity"></param>
        protected virtual void ConvertDwgObject(Entity entity)
        {
            string name = entity.GetType().Name;
            try
            {
                switch (name)
                {
                    case "DBText":
                        OnConvertDBText(entity as DBText);
                        break;
                    case "MText":
                        OnConvertMText(entity as MText);
                        break;
                    case "DBPoint":
                        OnConvertDBPoint(entity as DBPoint);
                        break;
                    case "Line":
                        OnConvertLine(entity as Line);
                        break;
                    case "Polyline":
                        OnConvertPolyline(entity as Polyline);
                        break;
                    case "Polyline2d":
                        OnConvertPolyline2d(entity as Polyline2d);
                        break;
                    case "Polyline3d":
                        OnConvertPolyline3d(entity as Polyline3d);
                        break;
                    case "Circle":
                        OnConvertCircle(entity as Circle);
                        break;
                    case "Arc":
                        OnConvertArc(entity as Arc);
                        break;
                    case "Ellipse":
                        OnConvertEllipse(entity as Ellipse);
                        break;
                    case "Spline":
                        OnConvertSpline(entity as Spline);
                        break;
                    case "BlockReference":
                        OnConvertBlockReference(entity as BlockReference);
                        break;
                    default:
                        OnConvertOthers(name, entity);
                        break;
                }
            }
            catch (Exception ex)
            {
                AddErrorLogItem($"编号为({entity.ObjectId.OldIdPtr})、类型为({name})的数据转换错误,{ex.Message}");
            }
        }

        /// <summary>
        /// 转换DBText类型的dwg数据
        /// </summary>
        /// <param name="dBText"></param>
        protected virtual void OnConvertDBText(DBText dBText)
        {

        }

        /// <summary>
        /// 转换MText类型的dwg数据
        /// </summary>
        /// <param name="dBText"></param>
        protected virtual void OnConvertMText(MText mText)
        {

        }

        /// <summary>
        /// 转换DBPoint类型的dwg数据
        /// </summary>
        /// <param name="DBPoint"></param>
        protected virtual void OnConvertDBPoint(DBPoint dBPoint)
        {

        }

        /// <summary>
        /// 转换Line类型的dwg数据
        /// </summary>
        /// <param name="Line"></param>
        protected virtual void OnConvertLine(Line line)
        {

        }

        /// <summary>
        /// 转换Polyline类型的dwg数据
        /// </summary>
        /// <param name="Polyline"></param>
        protected virtual void OnConvertPolyline(Polyline polyline)
        {

        }

        /// <summary>
        /// 转换polyline2D类型的dwg数据
        /// </summary>
        /// <param name="polyline2D"></param>
        protected virtual void OnConvertPolyline2d(Polyline2d polyline2D)
        {

        }

        /// <summary>
        /// 转换polyline3D类型的dwg数据
        /// </summary>
        /// <param name="Polyline3d"></param>
        protected virtual void OnConvertPolyline3d(Polyline3d polyline3D)
        {

        }

        /// <summary>
        ///转换circle类型的dwg数据
        /// </summary>
        /// <param name="circle"></param>
        protected virtual void OnConvertCircle(Circle circle)
        {

        }

        /// <summary>
        ///转换arc类型的dwg数据
        /// </summary>
        /// <param name="arc"></param>
        protected virtual void OnConvertArc(Arc arc)
        {

        }

        /// <summary>
        ///转换Ellipse类型的dwg数据
        /// </summary>
        /// <param name="arc"></param>
        protected virtual void OnConvertEllipse(Ellipse ellipse)
        {

        }

        /// <summary>
        ///转换Spline类型的dwg数据
        /// </summary>
        /// <param name="Spline"></param>
        protected virtual void OnConvertSpline(Spline spline)
        {

        }

        /// <summary>
        ///转换BlockReference类型的dwg数据
        /// </summary>
        /// <param name="BlockReference"></param>
        protected virtual void OnConvertBlockReference(BlockReference blockReference)
        {
            DBObjectCollection dBObjectCollection = new DBObjectCollection();
            blockReference.Explode(dBObjectCollection);
            foreach (DBObject dBObject in dBObjectCollection)
            {
                ConvertDwgObject(dBObject as Entity);
            }
        }

        /// <summary>
        /// 其他类型的
        /// 这里面没有捕捉的类型外
        /// </summary>
        /// <param name="entity"></param>
        protected virtual void OnConvertOthers(string name, Entity entity)
        {
            AddWraingLogItem($"类型为({name})的数据暂不能转换");
        }
    }
}
